package org.sensornet2010.alpha;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.microedition.io.Connector;
import javax.microedition.io.ContentConnection;
import javax.microedition.io.HttpConnection;


public class RemoteServer {

	public static String CGI_STATUS		=	"/server_state.php";
	public static String CGI_SENDDATA	=	"/senddata.php";
	private String url;
	
	public RemoteServer(String url){
		this.url = url;
	}

	public String getStatus(){
		String response = null;
		try {
			response = this.getViaContentConnection(this.url + CGI_STATUS);
		} catch (IOException e) {
			response = "ERROR:" + e.getMessage();
			//DEBUG: e.printStackTrace();
		}
		//TODO: configurable-debug
		//System.err.println("getStatus():");
		//System.err.println(response);
		return response;
	}
	public String sendData(SensorData data) {
		Hashtable params = new Hashtable();
		params.put("SENSOR_ID", data.getId());
		params.put("TIMESTAMP", ""+data.getTimestamp().getTime());
		params.put("DURATION", ""+data.getDuration());
		params.put("PROTOCOL", ""+data.getSensuinoVersion());
		String fileName = data.getId() + "_" + data.getTimestamp().getTime() +".amr";
		String response = this.fileUploadPOST(this.url + CGI_SENDDATA, data.getSound(), fileName, "binary/octet-stream", params);
		
		//TODO: configurable-debug
		//System.err.println("sendData():");
		//System.err.println(response);
		return response;
	}

	private String dummySendData(SensorData data) {

		String result = null;
		long millis = 1000;
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			throw new RuntimeException(e.toString());
		}
		Date date = new Date();
		result = date.toString();
		return result;
	}

	String getViaContentConnection(String url) throws IOException {
		ContentConnection c = null;
		DataInputStream dis = null;
		String s = "";

		try {
			c = (ContentConnection) Connector.open(url);
			int len = (int) c.getLength();
			dis = c.openDataInputStream();
			if (len > 0) {
				byte[] data = new byte[len];
				dis.readFully(data);
				s = new String(data, 0, len);
			} else {
				int ch;
				while ((ch = dis.read()) != -1) {
					byte[] data = new byte[1];
					data[0] = (byte) ch;
					s += new String(data, 0, 1);
				}
			}
		} finally {
			if (dis != null)
				dis.close();
			if (c != null)
				c.close();
		}
		return s;
	}
	
	String fileUploadPOST(String url, byte[] fileBytes, String fileName, String contentType, Hashtable params){
		String response = null;
		HttpMultipartRequest req;
		try {
			//req = new HttpMultipartRequest(url, params, "upload_field", "original_filename.png", "image/gif", fileBytes);
			req = new HttpMultipartRequest(url, params, "file", fileName, contentType, fileBytes);
			byte[] resp= req.send();
			response = new String(resp);
		} catch (Exception e) {
			//DEBUG: e.printStackTrace();
			throw new RuntimeException( "ERROR.fileUploadPOST:" + e.getClass() + "="+ e.getMessage());
		}
		return response;
	}
	
	class HttpMultipartRequest {
		/*
		 * Example code from: http://wiki.forum.nokia.com/index.php/HTTP_Post_multipart_file_upload_in_Java_ME
		 * 
			// -----Java client code
			// Here's a code snippet to upload a file via HttpMultipartRequest class:
			byte[] fileBytes = getFileBytes(); // retrieve file bytes with your own
												// code
			Hashtable params = new Hashtable();
			params.put("custom_param", "param_value");
			params.put("custom_param2", "param_value2");
			HttpMultipartRequest req = new HttpMultipartRequest(
					"http://www.server.com/uploadScript.php", params,
					"upload_field", "original_filename.png", "image/png", fileBytes);
			byte[] response = req.send();
			
			//----PHP server code
			<?php
				$filesize = filesize($_FILES['upload_field']['tmp_name']);
				echo "The uploaded file size is " . $filesize . " bytes\n";
	 			foreach($_POST as $key => $value)
				{
					echo "Parameter name: " . $key . ", value: " . $value . "\n";
				}
			?>
		 */
		
		
		static final String BOUNDARY = "----------V2ymHFg03ehbqgZCaKO6jy";

		byte[] postBytes = null;
		String url = null;

		public HttpMultipartRequest(String url, Hashtable params,
				String fileField, String fileName, String fileType,
				byte[] fileBytes) throws Exception {
			this.url = url;
			String boundary = getBoundaryString();
			String boundaryMessage = getBoundaryMessage(boundary, params,
					fileField, fileName, fileType);
			String endBoundary = "\r\n--" + boundary + "--\r\n";
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			bos.write(boundaryMessage.getBytes());
			bos.write(fileBytes);
			bos.write(endBoundary.getBytes());
			this.postBytes = bos.toByteArray();
			bos.close();
		}

		String getBoundaryString() {
			return BOUNDARY;
		}

		String getBoundaryMessage(String boundary, Hashtable params,
				String fileField, String fileName, String fileType) {
			StringBuffer res = new StringBuffer("--").append(boundary).append(
					"\r\n");
			Enumeration keys = params.keys();
			while (keys.hasMoreElements()) {
				String key = (String) keys.nextElement();
				String value = (String) params.get(key);

				res.append("Content-Disposition: form-data; name=\"").append(
						key).append("\"\r\n").append("\r\n").append(value)
						.append("\r\n").append("--").append(boundary).append(
								"\r\n");
			}
			res.append("Content-Disposition: form-data; name=\"").append(
					fileField).append("\"; filename=\"").append(fileName)
					.append("\"\r\n").append("Content-Type: ").append(fileType)
					.append("\r\n\r\n");
			return res.toString();
		}

		public byte[] send() throws Exception {
			HttpConnection hc = null;
			InputStream is = null;
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] res = null;
			Exception ex = null;
			try {
				hc = (HttpConnection) Connector.open(url);
				hc.setRequestProperty("Content-Type","multipart/form-data; boundary=" + getBoundaryString());
				hc.setRequestMethod(HttpConnection.POST);
				OutputStream dout = hc.openOutputStream();
				dout.write(postBytes);
				dout.close();
				int ch;
				is = hc.openInputStream();
				while ((ch = is.read()) != -1) {
					bos.write(ch);
				}
				res = bos.toByteArray();
			} catch (Exception e) {
				e.printStackTrace();
				ex = e;
			} finally {
				try {
					if (bos != null)
						bos.close();

					if (is != null)
						is.close();

					if (hc != null)
						hc.close();
				} catch (Exception e2) {
					e2.printStackTrace();
					ex = e2;
				}
			}
			if (ex != null)
				throw new RuntimeException("ERROR.send():" + ex.getClass() + "=" + ex.getMessage());
			return res;
		}
	}	
	
}
